package cn.mumzone.basic.dialog;

import android.app.Dialog;
import android.content.Context;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;

import cn.mumzone.basic.R;


/**
 * Created by lijiateng on 2018/7/2.
 * 自定义万能 Dialog
 */

public class AlertDialog extends Dialog {

    public AlertController mAlert;

    private static long sLastObjectCreatedTime = 0;

    public AlertDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);

        mAlert = new AlertController(this, getWindow());

    }

    public void setText(int viewId, CharSequence text) {
        mAlert.setText(viewId, text);
    }

    public void setOnClickListener(int viewId, View.OnClickListener listener) {
        mAlert.setOnClickListener(viewId, listener);
    }

    public void toggleShowEmpty(boolean isShowEmpty, int rootViewId) {
        if (isShowEmpty) {
            mAlert.showEmpty(rootViewId);
        } else {
            mAlert.restoreEmpty();
        }
    }

    public void toggleShowEmpty(boolean isShowEmpty, int rootViewId, int emptyResId, String emptyMsg) {
        this.toggleShowEmpty(isShowEmpty, rootViewId, emptyResId, emptyMsg, null, null);
    }

    public void toggleShowEmpty(boolean isShowEmpty, int rootViewId, int emptyResId, String emptyMsg, String btnMsg, View.OnClickListener onClickListener) {
        if (isShowEmpty) {
            mAlert.showEmpty(rootViewId, emptyResId, emptyMsg, btnMsg, onClickListener);
        } else {
            mAlert.restoreEmpty();
        }
    }

    public <V extends View> V getView(int viewId) {
        return mAlert.getView(viewId);
    }

    public static class Builder {

        public final AlertController.AlertParams P;
        private Context mContext;

        public Builder(Context context) {
            this(context, R.style.dialog);
            mContext = context;
        }

        public Builder(Context context, int themeResId) {
            P = new AlertController.AlertParams(context, themeResId);
        }

        public AlertController.AlertParams getAlertParams() {
            return P;
        }

        public Builder setContentView(int layoutResId) {
            P.mView = null;
            P.mViewLayoutResId = layoutResId;
            return this;
        }

        public Builder setContentView(View view) {
            P.mView = view;
            P.mViewLayoutResId = 0;
            return this;
        }

        public Builder setCancelViewId(int cancelViewId) {
            P.mCancelViewId = cancelViewId;
            return this;
        }

        public Builder setConfirmViewId(int confirmViewId) {
            P.mSingleConfirmViewId = confirmViewId;
            return this;
        }

        public Builder setDoubleConfirmViewId(int leftId, int rightId) {
            P.mLeftConfirmViewId = leftId;
            P.mRightConfirmViewId = rightId;
            return this;
        }

        public Builder setBottomTextViewId(int bottomTextViewId) {
            P.mBottomTextViewId = bottomTextViewId;
            return this;
        }

        public Builder setOnCancelListener(OnCancelListener onCancelListener) {
            P.mOnCancelListener = onCancelListener;
            return this;
        }

        public Builder setCancelableOntheOutside(boolean cancelable) {
            P.mCancelable = cancelable;
            return this;
        }

        /**
         * 因为 AlertController.AlertParams 只是暂时存放各种数据，最后的拼装在 apply() 方法中进行
         * 同时又会有多个按钮等待赋值，因此使用 map
         *
         * @param viewId
         * @param text
         * @return
         */
        public Builder setText(int viewId, CharSequence text) {
            P.mTextArray.put(viewId, text);
            return this;
        }

        public Builder setTextBackground(int viewId, int drawableResId) {
            P.mBackgroundResArray.put(viewId, drawableResId);
            return this;
        }

        public Builder setOnClickListener(int view, View.OnClickListener listener) {
            P.mClickArray.put(view, listener);
            return this;
        }

        /**
         * Sets the callback that will be called when the dialog is dismissed for any reason.
         *
         * @return This Builder object to allow for chaining of calls to set methods
         */
        public Builder setOnDismissListener(OnDismissListener onDismissListener) {
            P.mOnDismissListener = onDismissListener;
            return this;
        }

        /**
         * Sets the callback that will be called if a key is dispatched to the dialog.
         *
         * @return This Builder object to allow for chaining of calls to set methods
         */
        public Builder setOnKeyListener(OnKeyListener onKeyListener) {
            P.mOnKeyListener = onKeyListener;
            return this;
        }

        /**
         * 是否横向充满屏幕
         *
         * @return
         */
        public Builder fullWidth() {
            P.mWidth = ViewGroup.LayoutParams.MATCH_PARENT;
            return this;
        }

        /**
         * 从底部弹出
         *
         * @param isAnimation 是否有动画
         * @return
         */
        public Builder fromBottom(boolean isAnimation) {
            if (isAnimation) {
                P.mAnimation = R.style.dialog_from_bottom_anim;
            }
            P.mGravity = Gravity.BOTTOM;
            return this;
        }

        public Builder fromRight(boolean isAnimation) {
            if (isAnimation) {
                P.mAnimation = R.style.dialog_from_right_anim;
            }
            P.mGravity = Gravity.END;
            return this;
        }

        public Builder setWidthAndHeight(int width, int height) {
            P.mWidth = dip2px(mContext, width);
            P.mHeight = dip2px(mContext, height);

            if (width == ViewGroup.LayoutParams.MATCH_PARENT
                    || width == ViewGroup.LayoutParams.WRAP_CONTENT) {
                P.mWidth = width;
            }

            if (height == ViewGroup.LayoutParams.MATCH_PARENT
                    || height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                P.mHeight = height;
            }
            return this;
        }

        public Builder setGravity(int gravity) {
            P.mGravity = gravity;
            return this;
        }

        public void setBottomText(String text) {
            P.mTextArray.put(P.mBottomTextViewId, text);
        }

        /**
         * 对 AlertController.AlertParams 中设置的各种属性进行最后的拼装
         * 初始化一个 AlertDialog 的实例并进行返回
         *
         * @return
         */
        public AlertDialog create() {
            // We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param,
            // so we always have to re-set the theme
            final AlertDialog dialog = new AlertDialog(P.mContext, P.mThemeResId);
            P.apply(dialog.mAlert);
            dialog.setCancelable(P.mCancelable);
            if (P.mCancelable) {
                dialog.setCanceledOnTouchOutside(true);
            }
            dialog.setOnCancelListener(P.mOnCancelListener);
            dialog.setOnDismissListener(P.mOnDismissListener);
            if (P.mOnKeyListener != null) {
                dialog.setOnKeyListener(P.mOnKeyListener);
            }

            // 统一设置取消或确定点击事件，并向外暴露回到
            setClickListeners(dialog);

            return dialog;
        }

        /**
         * 统一设置取消或确定点击事件，并向外暴露回到
         *
         * @param dialog
         */
        private void setClickListeners(final AlertDialog dialog) {

            // 关闭按钮，点击后关闭弹窗
            if (P.mCancelViewId != 0) {
                dialog.getView(P.mCancelViewId).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        dialog.dismiss();
                    }
                });
            }

            // 单确认按钮
            if (P.mSingleConfirmViewId != 0 && mSingleConfirmListener != null) {
                dialog.getView(P.mSingleConfirmViewId).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        mSingleConfirmListener.onConfirmClicked(dialog);
                    }
                });
            }

            // 双按钮-左侧按钮
            if (P.mLeftConfirmViewId != 0 && mDoubleConfirmListener != null) {
                dialog.getView(P.mLeftConfirmViewId).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        mDoubleConfirmListener.onCancelClicked(dialog);
                    }
                });
            }

            // 双按钮-右侧按钮
            if (P.mRightConfirmViewId != 0 && mDoubleConfirmListener != null) {
                dialog.getView(P.mRightConfirmViewId).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        mDoubleConfirmListener.onConfirmClicked(dialog);
                    }
                });
            }
        }

        public AlertDialog show() {
            final AlertDialog dialog = create();
            if (System.currentTimeMillis() - sLastObjectCreatedTime > 1000) {
                dialog.show();
                sLastObjectCreatedTime = System.currentTimeMillis();
            }
            return dialog;
        }

        // 单确认按钮回调
        private OnSingleConfirmListener mSingleConfirmListener;

        public Builder setOnSingleConfirmListener(OnSingleConfirmListener listener) {
            this.mSingleConfirmListener = listener;
            return this;
        }

        public interface OnSingleConfirmListener {
            void onConfirmClicked(AlertDialog dialog);
        }

        // 确认 + 取消按钮回调
        private OnDoubleChoiceListener mDoubleConfirmListener;

        public Builder setOnDoubleChoiceListener(OnDoubleChoiceListener listener) {
            this.mDoubleConfirmListener = listener;
            return this;
        }

        public interface OnDoubleChoiceListener {
            void onCancelClicked(AlertDialog dialog);

            void onConfirmClicked(AlertDialog dialog);
        }

        public int dip2px(Context context, double dpValue) {
            float density = context.getResources().getDisplayMetrics().density;
            return (int) (dpValue * density + 0.5);
        }

    }


}
